package org.groupg.practice.data;

import org.groupg.practice.data.master.BitPackedDataStore;
import org.groupg.practice.data.master.CompressedColumnarStore;

import java.util.ArrayList;
import java.util.List;

public class RealWorldOptimizationTest {
    private static final int DATA_SIZE = 41297762;

    public static void main(String[] args) {
        PreciseMemoryTracker.memorySnapshot("启动后");

        // 生成测试数据
        System.out.println("生成测试数据...");
        int[] ids = generateIds(DATA_SIZE);
        long[] timestamps = generateTimestamps(DATA_SIZE);
        double[] values = generateValues(DATA_SIZE);
        String[] labels = generateLabels(DATA_SIZE);

        PreciseMemoryTracker.memorySnapshot("数据生成后");

        // 测试传统方式
        testTraditionalApproach(ids, timestamps, values, labels);

        // 测试位级压缩
        testBitPackedApproach(ids, timestamps, values, labels);

        // 测试列式压缩
        testColumnarCompression(ids, timestamps, values, labels);
    }

    private static void testTraditionalApproach(int[] ids, long[] timestamps,
                                              double[] values, String[] labels) {
        System.out.println("\n=== 传统List方式 ===");
        long startTime = System.currentTimeMillis();

        List<DataRecord> traditionalList = new ArrayList<>(DATA_SIZE);
        for (int i = 0; i < DATA_SIZE; i++) {
            traditionalList.add(new DataRecord(
                ids[i], timestamps[i], values[i], labels[i]
            ));
        }

        long time = System.currentTimeMillis() - startTime;
        PreciseMemoryTracker.memorySnapshot("传统List构建完成");
        System.out.printf("构建耗时: %,d ms%n", time);

        // 手动触发GC来观察真实内存
        System.gc();
        try { Thread.sleep(1000); } catch (InterruptedException e) {}
        PreciseMemoryTracker.memorySnapshot("GC后传统方式");
    }

    private static void testBitPackedApproach(int[] ids, long[] timestamps,
                                            double[] values, String[] labels) {
        System.out.println("\n=== 位级压缩方式 ===");
        long startTime = System.currentTimeMillis();

        long baseTimestamp = findMinTimestamp(timestamps);
        BitPackedDataStore packedStore = new BitPackedDataStore(DATA_SIZE, baseTimestamp);

        for (int i = 0; i < DATA_SIZE; i++) {
            packedStore.addRecord(i, ids[i], timestamps[i], values[i], labels[i]);
        }

        long time = System.currentTimeMillis() - startTime;
        long estimatedMemory = packedStore.calculateMemoryUsage();

        System.out.printf("构建耗时: %,d ms%n", time);
        System.out.printf("估算内存: %,d bytes (%.2f MB)%n",
            estimatedMemory, estimatedMemory / (1024.0 * 1024.0));

        PreciseMemoryTracker.memorySnapshot("位级压缩构建完成");
    }

    private static void testColumnarCompression(int[] ids, long[] timestamps,
                                              double[] values, String[] labels) {
        System.out.println("\n=== 列式压缩方式 ===");
        long startTime = System.currentTimeMillis();

        CompressedColumnarStore columnarStore =
            new CompressedColumnarStore(ids, timestamps, values, labels);

        long time = System.currentTimeMillis() - startTime;
        long memoryUsage = columnarStore.getMemoryUsage();

        System.out.printf("构建耗时: %,d ms%n", time);
        System.out.printf("压缩后内存: %,d bytes (%.2f MB)%n",
            memoryUsage, memoryUsage / (1024.0 * 1024.0));
    }

    // 数据生成方法
    private static int[] generateIds(int size) {
        int[] ids = new int[size];
        for (int i = 0; i < size; i++) {
            ids[i] = i; // 连续的ID
        }
        return ids;
    }

    private static long[] generateTimestamps(int size) {
        long[] timestamps = new long[size];
        long base = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            timestamps[i] = base + i * 1000L; // 每秒一条
        }
        return timestamps;
    }

    private static double[] generateValues(int size) {
        double[] values = new double[size];
        java.util.Random random = new java.util.Random(42);
        for (int i = 0; i < size; i++) {
            values[i] = random.nextDouble() * 1000.0;
        }
        return values;
    }

    private static String[] generateLabels(int size) {
        String[] labels = new String[size];
        String[] labelTemplates = {"type_a", "type_b", "type_c", "type_d", "type_e"};
        for (int i = 0; i < size; i++) {
            labels[i] = labelTemplates[i % labelTemplates.length];
        }
        return labels;
    }

    private static long findMinTimestamp(long[] timestamps) {
        long min = Long.MAX_VALUE;
        for (long ts : timestamps) {
            if (ts < min) min = ts;
        }
        return min;
    }

}